/******************************************************************************
 *  Copyright 2013 Bernhard Grünewaldt                                        *
 *                                                                            *
 *  Licensed under the Apache License, Version 2.0 (the "License");           *
 *  you may not use this file except in compliance with the License.          *
 *  You may obtain a copy of the License at                                   *
 *                                                                            *
 *      http://www.apache.org/licenses/LICENSE-2.0                            *
 *                                                                            *
 *  Unless required by applicable law or agreed to in writing, software       *
 *  distributed under the License is distributed on an "AS IS" BASIS,         *
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  *
 *  See the License for the specific language governing permissions and       *
 *  limitations under the License.                                            *
 ******************************************************************************/
package com.google.code.greenwood.confluencemavenreleaseinfomacro.macro.diff;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Map;

import org.apache.commons.httpclient.HttpException;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.SAXException;

import com.atlassian.cache.CacheManager;
import com.atlassian.confluence.content.render.xhtml.ConversionContext;
import com.atlassian.confluence.macro.Macro;
import com.atlassian.confluence.macro.MacroExecutionException;
import com.atlassian.renderer.RenderContext;
import com.atlassian.renderer.v2.RenderMode;
import com.atlassian.renderer.v2.macro.BaseMacro;
import com.atlassian.renderer.v2.macro.MacroException;
import com.google.code.greenwood.confluencemavenreleaseinfomacro.parser.DomDocumentToReleaseInfoParser;
import com.google.code.greenwood.confluencemavenreleaseinfomacro.parser.HttpReleaseInfoDownloader;
import com.google.code.greenwood.confluencemavenreleaseinfomacro.pojo.ReleaseInformation;
import com.google.code.greenwood.confluencemavenreleaseinfomacro.pojo.StaticClassWrapper;
import com.google.code.greenwood.confluencemavenreleaseinfomacro.pojo.diff.ReleaseInformationDiff;
import com.google.code.greenwood.confluencemavenreleaseinfomacro.transformer.HtmlTransformer;


public class ReleaseInfoDiffMacro extends BaseMacro implements Macro {
	
	private static final Logger log = LoggerFactory.getLogger(ReleaseInfoDiffMacro.class);

	// mockable
	private StaticClassWrapper staticClassWrapper;
	// mockable
	private HtmlTransformer htmltransformer;
	
	// SpringDI by Confluence
	private CacheManager cacheManager;
	public final static String RELEASEINFO_MACRO_CACHE_KEY = "confluencemavenreleaseinfomacro";
	// cache expires after 15 mins
	private long cacheTime = 15*60;
	
	public final static String urlToFirstReleasePomXmlKey = "urlToFirstReleasePomXml";
	public final static String urlToSecondReleasePomXmlKey = "urlToSecondeleasePomXml";	
	public final static String httpUsernameKey = "httpUsername";
	public final static String httpPasswordKey = "httpPassword";
	
	
	private static final String errorHtmlPrefix = "<div style=\"border:1px solid #e02828;color:#e02828;font-weight:bold;padding:6px;background-color:#ffdede;\">";
	private static final String errorHtmlSuffix = "</div>";

	private static final String infoHtmlPrefix = "<div style=\"border:1px solid #2445bd;color:#2445bd;font-weight:bold;padding:6px;background-color:#dee5ff;\">";
	private static final String infoHtmlSuffix = "</div>";
	
	@Override
	public String execute(Map<String, String> params, String body, ConversionContext ctx) throws MacroExecutionException {
		String httpUsername = null;
		String httpPassword = null;
		String urlToFirstReleasePomXml = null;
		String urlToSecondReleasePomXml = null;
		
		
		//Cache cache = cacheManager.getCache(RELEASEINFO_MACRO_CACHE_KEY);
		
		
		if (params.containsKey(urlToFirstReleasePomXmlKey)) {
			urlToFirstReleasePomXml = params.get(urlToFirstReleasePomXmlKey);
        }
        if (params.containsKey(urlToSecondReleasePomXmlKey)) {
        	urlToSecondReleasePomXml = params.get(urlToSecondReleasePomXmlKey);
        }
        if (params.containsKey(httpUsernameKey)) {
        	httpUsername = params.get(httpUsernameKey);
        }
        if (params.containsKey(httpPasswordKey)) {
        	httpPassword = params.get(httpPasswordKey);
        }
        
        if (urlToFirstReleasePomXml != null && urlToSecondReleasePomXml != null) {
        
        String bodycontent = null;
			try {

				HttpReleaseInfoDownloader down = new HttpReleaseInfoDownloader();
				File firstParentpom = down.downloadMavenReleaseRecursively(new URL(urlToFirstReleasePomXml), httpUsername,httpPassword);
				File secondParentpom = down.downloadMavenReleaseRecursively(new URL(urlToSecondReleasePomXml), httpUsername,httpPassword);
				
				DomDocumentToReleaseInfoParser parser = new DomDocumentToReleaseInfoParser();
				ReleaseInformation firstReleaseinfo = parser.parsePomFilesRecursive(firstParentpom, true);
				ReleaseInformation secondReleaseinfo = parser.parsePomFilesRecursive(secondParentpom, true);
				
				// cleanup 
				FileUtils.deleteDirectory(firstParentpom.getParentFile());
				FileUtils.deleteDirectory(secondParentpom.getParentFile());
				
				ReleaseInformationDiff diff = new ReleaseInformationDiff();
				diff.setReleaseInformationOne(firstReleaseinfo);
				diff.setReleaseInformationTwo(secondReleaseinfo);

				bodycontent = htmltransformer.toHtml(diff, HtmlTransformer.Macroselector.DIFFMACRO, null);
				
				return bodycontent;
	
			} catch (SAXException e) {
				System.err.println("SAXException: "+e.getMessage());
				return errorHtmlPrefix+staticClassWrapper.i18n_getText("releaseinfomacro.exceptiontext.saxexception")+errorHtmlSuffix;
			} catch (MalformedURLException e) {
				System.err.println("MalformedURLException: "+e.getMessage());
				return errorHtmlPrefix+staticClassWrapper.i18n_getText("releaseinfomacro.exceptiontext.malformedurlexception")+errorHtmlSuffix;
			} catch (HttpException e) {
				System.err.println("HttpException: "+e.getMessage());
				return errorHtmlPrefix+staticClassWrapper.i18n_getText("releaseinfomacro.exceptiontext.httpexception", new String[]{e.getMessage()})+errorHtmlSuffix;
			} catch (IOException e) {
				System.err.println("IOException: "+e.getMessage());
				return errorHtmlPrefix+staticClassWrapper.i18n_getText("releaseinfomacro.exceptiontext.ioexception", new String[]{e.getMessage()})+errorHtmlSuffix;
			} catch(Exception e) {
				System.err.println("Exception: "+e.getMessage());
				throw new MacroExecutionException(e);			
			}
        }
        return  infoHtmlPrefix+staticClassWrapper.i18n_getText("releaseinfomacro.norurl.specified")+infoHtmlSuffix;
	}


	@Override
	public BodyType getBodyType() {
		return BodyType.NONE;
	}


	@Override
	public OutputType getOutputType() {
		return OutputType.INLINE;
	}
	
	@SuppressWarnings("unchecked")
	@Override
    public String execute(@SuppressWarnings("rawtypes") Map params, String body, RenderContext renderContext) throws MacroException
    {
        try
        {
            return execute(params, body, (ConversionContext) null);
        }
        catch(MacroExecutionException e)
        {
            throw new MacroException(e);
        }
    }


	@Override
	public RenderMode getBodyRenderMode() {
		return RenderMode.INLINE;
	}


	@Override
	public boolean hasBody() {
		return false;
	}



	public void setCacheManager(CacheManager cacheManager) {
		this.cacheManager = cacheManager;
	}


	public void setCacheTime(long cacheTime) {
		this.cacheTime = cacheTime;
	}


	public void setStaticClassWrapper(StaticClassWrapper staticClassWrapper) {
		this.staticClassWrapper = staticClassWrapper;
	}


	public void setHtmltransformer(HtmlTransformer htmltransformer) {
		this.htmltransformer = htmltransformer;
	}



	
	
	

	
    
}
